#include "mainwidget.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QLabel>

#include "sessionfriendarea.h"
#include "messageeditarea.h".h"

MainWidget* MainWidget::instance = nullptr;

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
{
    this->setWindowTitle("我的聊天室");
    this->setWindowIcon(QIcon(":/resource/image/logo.png"));

    // 初始化界面
    this->initMainWidget();
    this->initLeftWidget();
    this->initMidWidget();
    this->initRightWidget();

    // 连接按钮和信号槽
    this->initSignalSlot();
}

MainWidget *MainWidget::getInstance()
{
    if(instance == nullptr) {
        // 父指针为空,默认父节点是桌面
        instance = new MainWidget();
    }
    return instance;
}

MainWidget::~MainWidget() {}

void MainWidget::initMainWidget()
{
    this->setMinimumSize(900, 600);

    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(0); // layout中元素之间的间距
    layout->setContentsMargins(0, 0, 0, 0); // layout中元素的外边距
    this->setLayout(layout);

    windowLeft = new QWidget();
    windowMid = new QWidget();
    windowRight = new QWidget();
    windowLeft->setFixedWidth(70);
    windowMid->setFixedWidth(250);
    windowRight->setMinimumWidth(500);
    windowLeft->setStyleSheet("QWidget { background-color: rgb(25, 25, 25); }");
    windowMid->setStyleSheet("QWidget { background-color: rgb(245, 245, 245); }");
    windowRight->setStyleSheet("QWidget { background-color: rgb(225, 225, 225); }");

    layout->addWidget(windowLeft);
    layout->addWidget(windowMid);
    layout->addWidget(windowRight);
}

void MainWidget::initLeftWidget()
{
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setContentsMargins(0, 50, 0, 0);
    windowLeft->setLayout(layout);

    QString btnStyle = "QPushButton { border:none; }";
    btnStyle += "QPushButton:hover { background-color:rgb(150, 150, 150); }";

    userAvatar = new QPushButton();
    userAvatar->setFixedSize(50, 50);
    // userAvatar->setIcon(QIcon(":/resource/image/default_avatar.png"));
    userAvatar->setIconSize(QSize(50, 50));
    userAvatar->setStyleSheet(btnStyle);

    sessionListBtn = new QPushButton();
    sessionListBtn->setFixedSize(45, 45);
    sessionListBtn->setIconSize(QSize(45, 45));
    sessionListBtn->setIcon(QIcon(":/resource/image/sessionList_active.png"));
    sessionListBtn->setStyleSheet(btnStyle);

    friendListBtn = new QPushButton();
    friendListBtn->setFixedSize(45, 45);
    friendListBtn->setIconSize(QSize(45, 45));
    friendListBtn->setIcon(QIcon(":/resource/image/friendList_inactive.png"));
    friendListBtn->setStyleSheet(btnStyle);

    applyListBtn = new QPushButton();
    applyListBtn->setFixedSize(45, 45);
    applyListBtn->setIconSize(QSize(45, 45));
    applyListBtn->setIcon(QIcon(":/resource/image/applyList_inactive.png"));
    applyListBtn->setStyleSheet(btnStyle);

    layout->addWidget(userAvatar, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(sessionListBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(friendListBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(applyListBtn, 1, Qt::AlignTop | Qt::AlignHCenter);
    layout->addStretch(3);
}

void MainWidget::initMidWidget()
{
    QGridLayout* layout = new QGridLayout();
    layout->setHorizontalSpacing(0);
    layout->setVerticalSpacing(10);
    layout->setContentsMargins(0, 10, 0, 0);
    windowMid->setLayout(layout);

    // 搜索框
    searchEdit = new QLineEdit();
    searchEdit->setFixedHeight(30);
    searchEdit->setPlaceholderText("搜索");
    QString style1 = "QLineEdit { border-radius: 10px; "
                    "background-color:rgb(22, 22, 22); "
                    "padding: 5px; "
                    "font-size: 15px; } ";
    searchEdit->setStyleSheet(style1);

    // 添加好友按钮
    addFriendBtn = new QPushButton();
    addFriendBtn->setFixedSize(30, 30);
    addFriendBtn->setIcon(QIcon(":/resource/image/add_friend.png"));
    QString style2 = "QPushButton { background-color:rgb(22, 22, 22) } ";
    style2 += "QPushButton:pressed { background-color:rgb(150, 150, 150)} ";
    addFriendBtn->setStyleSheet(style2);

    // 会话列表中的好友区域
    friendArea = new SessionFriendArea();
    friendArea->setStyleSheet("SessionFriendArea { background-color:rgb(200, 200, 200); }");

    // 为了让会话列表中搜索框所在行距离左右有些边距,而不影响好友区域,添加一些空白区域
    QWidget* space1 = new QWidget();
    space1->setFixedWidth(10);
    QWidget* space2 = new QWidget();
    space2->setFixedWidth(10);
    QWidget* space3 = new QWidget();
    space3->setFixedWidth(10);

    layout->addWidget(space1, 0, 0);
    layout->addWidget(searchEdit, 0, 1);
    layout->addWidget(space2, 0, 2);
    layout->addWidget(addFriendBtn, 0, 3);
    layout->addWidget(space3, 0, 5);
    layout->addWidget(friendArea, 1, 0, 1, 6);
}

void MainWidget::initRightWidget()
{
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setAlignment(Qt::AlignTop);
    windowRight->setLayout(layout);

    // 1.顶部区域
    QWidget* upArea = new QWidget();
    upArea->setFixedHeight(51);
    upArea->setObjectName("title");
    upArea->setStyleSheet("#title { border-bottom: 1px solid rgb(200, 200, 200); "
                          "border-left: 1px solid rgb(200, 200, 200); } ");
    layout->addWidget(upArea);

    // 给顶部区域添加 label 和 button
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);
    hlayout->setContentsMargins(10, 0, 10, 0);
    upArea->setLayout(hlayout);

    label = new QLabel();
    // label->setText("fsdfsdfsdfsdf");
    label->setStyleSheet("QLabel { font-size: 30px; "
                         "border-bottom:1px solid rgb(200, 200, 200); "
                         "color:rgb(1, 1, 1); }");

    moreBtn = new QPushButton();
    moreBtn->setFixedSize(40, 40);
    moreBtn->setIcon(QIcon(":/resource/image/more.png"));
    moreBtn->setIconSize(QSize(40, 40));
    moreBtn->setStyleSheet("QPushButton:pressed { background-color:rgb(200, 200, 200); }");

    hlayout->addWidget(label);
    hlayout->addWidget(moreBtn);

    // 2.消息展示区
    msgShowArea = new MessageShowArea();
    msgShowArea->setStyleSheet("MessageShowArea { background-color:rgb(1, 1, 1)}; ");
    layout->addWidget(msgShowArea, 2);

    // 3.消息编辑区
    msgEditArea = new MessageEditArea();
    msgEditArea->setStyleSheet("MessageEditArea { background-color:rgb(100, 100, 100); }; ");
    layout->addWidget(msgEditArea, 1);
}

void MainWidget::initSignalSlot()
{
    // 会话/好友/申请 列表按钮
    connect(this->sessionListBtn, &QPushButton::clicked, this, &MainWidget::switchTabToSession);
    connect(this->friendListBtn, &QPushButton::clicked, this, &MainWidget::switchTabToFriend);
    connect(this->applyListBtn, &QPushButton::clicked, this, &MainWidget::switchTabToApply);

    // 点击头像按钮,弹出个人信息对话框
    connect(userAvatar, &QPushButton::clicked, this, [this](){
        SelfInfoWidget* selfInfo = new SelfInfoWidget(this);
        selfInfo->exec();   // 模态显示
    });

    // 点击会话详情按钮,弹出对话框
    // click sesssion detail button, pop up dialog
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    connect(moreBtn, &QPushButton::clicked, this, [=](){
        model::ChatSessionInfo* info = dataCenter->findChatSessionInfoById(dataCenter->getCurrentSessionId());
        if(info == nullptr) {
            Toast::makeToast("no session selected");
            return;
        }
        bool isSignalChat = info->userId == "" ? false : true;

        if(isSignalChat) {
            SessionDetailWdiget* sessionDetailWidget = new SessionDetailWdiget(info->userId, this);
            sessionDetailWidget->exec();
        } else {
            GrounpSessionDetailWidget* group = new GrounpSessionDetailWidget(this);
            group->exec();
        }
    });

    // 点击添加好友按钮,弹出对话框
    connect(addFriendBtn, &QPushButton::clicked, this, [=](){
        AddFriendDialog* addFriendDialog = new AddFriendDialog(this);
        addFriendDialog->exec();
    });

    // 在搜索框中输入内容,弹出添加好友对话框
    connect(searchEdit, &QLineEdit::textEdited, this, [=](){
        AddFriendDialog* dialog = new AddFriendDialog(this);
        // 将搜索框输入的内容添加到好友对话框中的搜索框
        QString text = searchEdit->text();
        dialog->setText(text);
        // 清空搜索框的内容
        searchEdit->setText("");
        dialog->exec();
    });

    // 点击历史消息按钮,弹出历史消息对话框
    connect(msgEditArea->getHistoryBtn(), &QPushButton::clicked, this, [=](){
        HistoryMessageWidget* history = new HistoryMessageWidget(this);
        history->exec();
    });

    // get personal information from server
    dataCenter->getMyselfAsync();
    connect(dataCenter, &model::DataCenter::getMyselfDone, this, [=](){
        userAvatar->setIcon(dataCenter->getMyself()->avatar);
    });

    // load friend list
    this->loadFriendList();

    // load session list
    this->loadSessionList();

    // load apply list
    this->loadApplyList();

    connect(dataCenter, &model::DataCenter::modifyAvatarDone, this, [=](){
        userAvatar->setIcon(dataCenter->getMyself()->avatar);
    });

    connect(dataCenter, &model::DataCenter::deleteFriendDone, this, [=](){
        this->updateFriendList();
        this->updateChatSessionList();
    });

    connect(dataCenter, &model::DataCenter::clearCurrentChatSession, this, [=](){
        label->setText("");
        msgShowArea->clear();
        dataCenter->setCurrentSessionId("");
    });

    connect(dataCenter, &model::DataCenter::sendFriendApplyDone, this, [=](){
        Toast::makeToast("好友申请已发送");
    });

    connect(dataCenter, &model::DataCenter::addFriendApplyDone, this, [=](){
        this->updateApplyList();
    });

    // accept friend apply
    connect(dataCenter, &model::DataCenter::acceptFriendApplyDone, this, [=](){
        this->updateApplyList();
        this->updateFriendList();
    });

    connect(dataCenter, &model::DataCenter::agreeFriendApplyDone, this, [=](){
        this->updateFriendList();
    });

    // reject friend apply
    connect(dataCenter, &model::DataCenter::rejectFriendApplyDone, this, [=](){
        this->updateApplyList();
    });

    connect(dataCenter, &model::DataCenter::createGroupChatSessionDone, this, [=](){
        Toast::makeToast("creat group chat has been sent");
    });

    connect(dataCenter, &model::DataCenter::newChatSessionDone, this, [=](){
        this->updateChatSessionList();
        Toast::makeToast("a new group chat has been created");
    });
}

void MainWidget::loadRecentMessage(const QString &chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getRecentMessageList(chatSessionId) != nullptr) {
        // load data from memory
        this->updateRecentMessage(chatSessionId);
    } else {
        // load data from server
        connect(dataCenter, &model::DataCenter::getRecentMessageListDone, this, &MainWidget::updateRecentMessage, Qt::UniqueConnection);
        dataCenter->getRecentMessageListAsync(chatSessionId, true);
    }
}

void MainWidget::updateRecentMessage(const QString& chatSessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<Message>* list = dataCenter->getRecentMessageList(chatSessionId);

    msgShowArea->clear();
    for(auto &e : *list) {
        bool isLeft = (e.sender.userId == dataCenter->getMyself()->userId ? false : true);
        msgShowArea->addMsgItem(isLeft, e);
    }

    // set session title
    model::ChatSessionInfo* info = dataCenter->findChatSessionInfoById(chatSessionId);
    if(info != nullptr) {
        label->setText(info->sessionName);
    }

    // set current session
    dataCenter->setCurrentSessionId(chatSessionId);

    // put the vertical bar of MsgShowArea to the end
    msgShowArea->verticalBarToEnd();

}

void MainWidget::switchToSession(const QString &userId)
{
    // 1.select the sepcified session and move it to the top
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    model::ChatSessionInfo* info = dataCenter->findChatSessionInfoByUserId(userId);
    dataCenter->topChatSesssionInfo(*info);
    // 2.switch to SessionList tab
    this->switchTabToSession();
    // 3.update
    friendArea->clickItem(0);
}

MessageShowArea *MainWidget::getMessageShowArea()
{
    return msgShowArea;
}

// 切换标签页到会话列表
void MainWidget::switchTabToSession()
{
    this->curTab = SESSION_LIST;
    sessionListBtn->setIcon(QIcon(":/resource/image/sessionList_active.png"));
    friendListBtn->setIcon(QIcon(":/resource/image/friendList_inactive.png"));
    applyListBtn->setIcon(QIcon(":/resource/image/applyList_inactive.png"));
    this->loadSessionList();
}

// 切换标签页到好友列表
void MainWidget::switchTabToFriend()
{
    this->curTab = FRIEND_LIST;
    friendListBtn->setIcon(QIcon(":/resource/image/friendList_active.png"));
    sessionListBtn->setIcon(QIcon(":/resource/image/sessionList_inactive.png"));
    applyListBtn->setIcon(QIcon(":/resource/image/applyList_inactive.png"));
    this->loadFriendList();
}

// 切换标签页到申请列表
void MainWidget::switchTabToApply()
{
    this->curTab = APPLY_LIST;
    applyListBtn->setIcon(QIcon(":/resource/image/applyList_active.png"));
    friendListBtn->setIcon(QIcon(":/resource/image/friendList_inactive.png"));
    sessionListBtn->setIcon(QIcon(":/resource/image/sessionList_inactive.png"));
    this->loadApplyList();
}

void MainWidget::loadSessionList()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getChatSessionList() != nullptr) {
        // load data from memory
        this->updateChatSessionList();
    } else {
        // load data from server
        connect(dataCenter, &model::DataCenter::getChatSessionListDone, this, &MainWidget::updateChatSessionList, Qt::UniqueConnection);
        dataCenter->getChatSessionListAsync();
    }
}

void MainWidget::loadFriendList()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getFriendList() != nullptr) {
        // load data from memory
        this->updateFriendList();
    } else {
        // load data from server
        connect(dataCenter, &model::DataCenter::getFriendListDone, this, &MainWidget::updateFriendList, Qt::UniqueConnection);
        dataCenter->getFriendListAsync();
    }
}

void MainWidget::loadApplyList()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(dataCenter->getApplyList() != nullptr) {
        // load data from memory
        this->updateApplyList();
    } else {
        // load data from server
        connect(dataCenter, &model::DataCenter::getApplyListDone, this, &MainWidget::loadApplyList, Qt::UniqueConnection);
        dataCenter->getApplyListAsync();
    }
}

void MainWidget::updateFriendList()
{
    if(curTab != FRIEND_LIST) {
        return;
    }

    friendArea->clear();
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::UserInfo>* list = dataCenter->getFriendList();
    for(auto &e : *list) {
        friendArea->addItem(FriendType, e.userId, e.avatar, e.nickname, e.description);
    }
}

void MainWidget::updateChatSessionList()
{
    if(curTab != SESSION_LIST) {
        return;
    }
    friendArea->clear();
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::ChatSessionInfo>* list = dataCenter->getChatSessionList();
    for(auto &e : *list) {
        if(e.lastMessage.type == model::TEXT_TYPE) {
            friendArea->addItem(SessionType, e.sessionId, e.avatar, e.sessionName, e.lastMessage.content);
        } else if(e.lastMessage.type == model::FILE_TYPE) {
            friendArea->addItem(SessionType, e.sessionId, e.avatar, e.sessionName, "[file]");
        } else if(e.lastMessage.type == model::IMAGE_TYPE) {
            friendArea->addItem(SessionType, e.sessionId, e.avatar, e.sessionName, "[image]");
        } else if(e.lastMessage.type == model::SPEECH_TYPE) {
            friendArea->addItem(SessionType, e.sessionId, e.avatar, e.sessionName, "[speech]");
        } else {
            LOG() << "unknown message type";
        }
    }
}

void MainWidget::updateApplyList()
{
    if(curTab != APPLY_LIST) {
        return;
    }

    friendArea->clear();
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::UserInfo>* list = dataCenter->getApplyList();
    for(auto &e : *list) {
        friendArea->addItem(ApplyType, e.userId, e.avatar, e.nickname, "");
    }
}
